package eureka.consumer.redissonlock.review.conf;
import cn.hutool.core.util.StrUtil;
import eureka.consumer.redissonlock.BaseRedisProperty;
import eureka.consumer.redissonlock.review.impl.RedissonDistributeLockImpl;
import eureka.consumer.redissonlock.review.lockinter.DistributeLockTemplate;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RedissonClient;
import org.redisson.config.Config;
import org.redisson.config.SingleServerConfig;
import org.redisson.config.TransportMode;
import org.springframework.beans.factory.FactoryBean;

import javax.annotation.PreDestroy;

/**
 * @Author RenPu
 * @Date 2023/10/7 16:19
 * @Version 1.0
 * @Description:
 **/
@Slf4j
public class DistributeLockFactoryBean implements FactoryBean<DistributeLockTemplate> {


    private final RedissonClient redisson;
    private DistributeLockTemplate distributeLockTemplate;

    private LockMode lockMode;


    public DistributeLockFactoryBean(BaseRedisProperty baseRedisProperty) {
        log.info("init redisson: {}", baseRedisProperty.toString());
        String mode = baseRedisProperty.getRedisson().getMode();

        //1：获取ip+port
        Integer port = baseRedisProperty.getPort();
        String host = baseRedisProperty.getHost();

        BaseRedisProperty.Redisson redisson=baseRedisProperty.getRedisson();

        //2:创建Redisson配置类，设置网络通信模型例如：NIO,EPLLO等，超时参数

        Config config = new Config();
        if (TransportMode.EPOLL.name().equalsIgnoreCase(redisson.getTransportMode())) {
            config.setTransportMode(TransportMode.EPOLL);
        }
        SingleServerConfig useSingleServer = config.useSingleServer();
        useSingleServer.setAddress("redis://"+host+":"+port);
        useSingleServer.setTimeout(redisson.getTimeOut());
        useSingleServer.setConnectionPoolSize(redisson.getPoolSize());
        //3:根据配置得参数密码，进行设置
        if(StrUtil.isNotBlank(baseRedisProperty.getPassword())){
            log.info("redisson 密码不为空，设置密码");
            useSingleServer.setPassword(baseRedisProperty.getPassword());
        }

        //4：设置链接超时时间
        useSingleServer.setPingConnectionInterval(1000);
        useSingleServer.setConnectionMinimumIdleSize(redisson.getMinIdleSize());

        this.redisson = Redisson.create(config);
        setMode(mode);
    }




    @PreDestroy
    public void destory(){
        log.info("分布式锁模板，开始销毁！！！！");
        redisson.shutdown();
    }


    /**
     * 获取分布式锁实现得对象
     * @return
     * @throws Exception
     */
    @Override
    public DistributeLockTemplate getObject() throws Exception {
        switch (lockMode){
            case SINGLE:
                distributeLockTemplate= new RedissonDistributeLockImpl(redisson);
            break;
        }
        return distributeLockTemplate;
    }


    @Override
    public Class<?> getObjectType() {
        return DistributeLockTemplate.class;
    }


    @Override
    public boolean isSingleton() {
        return true;
    }



    /**
     * 匹配分布式锁得模式
     * @param modeName
     */
    public  void setMode(String modeName){
        if(StrUtil.isBlank(modeName)){
            throw new RuntimeException("分布式锁模式，配置为空！！！！");
        }
        lockMode=LockMode.parse(modeName);
        if(lockMode==null){
            throw new RuntimeException("不支持当前配置得分布式锁模式，请重新核对！！！！");
        }
    }

    private enum LockMode {
        SINGLE;
        public static LockMode parse(String key){
            for (LockMode lockMode : LockMode.values()) {
                if(lockMode.name().equals(key.toUpperCase())){
                    return lockMode;
                }

            }
            return null;
        }


    }
}
